home *** CD-ROM | disk | FTP | other *** search
/ Trading on the Edge / Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin / pc / mac_file / vendor_d / neuralwa / nw2v50 / automate.c < prev    next >
Text File  |  1993-08-23  |  65KB  |  1,695 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*  Automate.c - A User Control program to batch-process many of the        */
  4. /*  Professional II/PLUS commands.  Multiple network names and tasks to be  */
  5. /*  performed are read from file automate.dat, with results written back    */
  6. /*  into automate.dat.  See shipped automate.dat for example of syntax.     */
  7. /*                                                                          */
  8. /*  This program requires version 5.0 of NeuralWorks Professional II/PLUS.  */
  9. /*                                                                          */
  10. /*  version 1.0                          Copyright 1993 by NeuralWare Inc.  */
  11. /*                                                                          */
  12. /*  edit history...                                                         */
  13. /*     07/31/93 - v1.0 release.          Bob Everly                         */
  14. /*                                                                          */
  15. /****************************************************************************/
  16.  
  17. #define UIO_SERVER             1
  18. #define SERVER_EMULATOR_FILE   1
  19. #define SKIP_COMPAT_DATA       1
  20. #include "userutl.h"
  21. #include "uio_strc.h"
  22. #include "uio_tran.h"
  23. #include "uio_reqs.pro"
  24. #include "uio_cmds.pro"
  25.  
  26. /*********** global variables and user #includes are entered here **********/
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <math.h>
  32. #include <ctype.h>          /* for tolower() */
  33.  
  34. NINT preScan        ARGLIST (( ));
  35. NINT processOneTask ARGLIST (( NINT ));
  36. NINT disableOutput  ARGLIST (( ));
  37. NINT runHoldout     ARGLIST (( ));
  38. NINT parseString    ARGLIST (( TEXT **, TEXT *, TEXT * ));
  39. NINT parseLong      ARGLIST (( TEXT **, SL * ));
  40. NINT parseInteger   ARGLIST (( TEXT **, NINT * ));
  41. NINT parseReal      ARGLIST (( TEXT **, SREAL * ));
  42. NINT fileNotFound   ARGLIST (( TEXT *,  TEXT *, NINT ));
  43. VOID showMsg        ARGLIST (( TEXT *,  NINT ));
  44. #ifdef MAC
  45. OSErr SetTypeAndCreator ARGLIST(( char *, char *, char *, short));
  46. #endif /* MAC */
  47.  
  48. #define DATLINELEN   500    /* max line length in automate.dat */
  49. #define DISABLEPES    50    /* max PEs disabled at once (must fit in DATLINELEN) */
  50. #define MAXFILESPEC   50    /* max chrs in a filename */
  51. #define NNPLINELEN  1500    /* max line length of *.nnp (Conf.Matrix output) */
  52. #define OPEN           1    /* taskID's - understood tasks */
  53. #define LEARN          2
  54. #define RECALL         3
  55. #define TEST           4
  56. #define SAVEBEST       5
  57. #define INITIALIZE     6
  58. #define RANDOMSEED     7
  59. #define DISABLE        8
  60. #define DISABLE_ALL    9
  61. #define SAVENET       10
  62. #define SETCMD        11    /* LearnFile, RecallFile, TestFile, Disable */
  63. #define HOLDOUT       12
  64.  
  65. #define TASK_OK        0    /* Task OK */
  66. #define TASK_ERROR    -1    /* Task Error */
  67. #define TASK_INTRPT   -2    /* Task Interrupted */
  68.  
  69. #ifdef THINK_C
  70. #define EolChr "\r"
  71. #else
  72. #define EolChr "\n"
  73. #endif
  74.  
  75. #define USER_INTRPT 0x0002
  76.  
  77. TEXT  NetworkFile[MAXFILESPEC]; /* net filename, for open */
  78. TEXT  SavenetFile[MAXFILESPEC]; /* net filename, for savnet */
  79. TEXT  LearnFile[MAXFILESPEC];   /* alternate *.nna file, for learn & savebest */
  80. TEXT  TestFile[MAXFILESPEC];    /* alternate *.nna file, for recall, test, disable */
  81. SL    Long1, Long2, Long3;      /* args for learn & savebest */
  82. SREAL SbPruneTolerance;         /* prune tolerance for savebest pruning */
  83. NINT  SbPruneMaxPEs;            /* max number of PEs to prune during savebest pruning */
  84. NINT  RandomSeed;               /* arg for randomseed task */
  85. NINT  PeNumbers[DISABLEPES];    /* pe list, for disable */
  86. NINT  IsSetLearn, IsSetTest;    /* flags== 1 for alternate learn/recall/test files */
  87. NINT  IsSetDisable;             /* flag == 1 for disable-PEs-and-save-net */
  88. NINT  FirstDisableTask;         /* flag == 1 upon first encounter of disable in this net */
  89. NINT  NumInputPEs;              /* input pe count, for disable */
  90. SREAL BaselineSum;              /* sum of R values for disable's baseline test */
  91. SREAL SigmaStart, SigmaStop, SigmaStep; /* varies PNN/GRNN holdout Sigma Scale */
  92. NINT  xSize, xChrSize, ySize, yChrSize; /* graphics characteristics */
  93.  
  94. /********************* end of user global definitions **********************/
  95.  
  96. #ifdef MAC
  97. #include "macuio.redef"
  98. #endif
  99.  
  100. /**************************************************************************/
  101. /*  Only functions UIO_Init(), UIO_Term() and especially UIO_Attention()  */
  102. /*  are used by a User Control program.  Code is added into these three   */
  103. /*  functions.  User written C functions can also be added and called.    */
  104. /**************************************************************************/
  105. NINT UIO_Init(file)
  106. TEXT *file;
  107. {
  108.    /* Certain compilers yield warnings when variables are declared within  */
  109.    /* functions but never used; hence the 'compiler be quiet!' lines.      */
  110.    file=file;      /* compiler be quiet! */
  111.    return(UIO_OK);
  112. }
  113.  
  114. NINT UIO_Term(process)
  115. NINT process;
  116. {
  117.    process = process;    /* compiler be quiet! */
  118.    return(UIO_OK);
  119. }
  120.  
  121. /**************************************************************************/
  122. /*   UIO_Attention() is used here as a 'driver', reading and parsing      */
  123. /*   tasks from automate.dat.                                             */
  124. /**************************************************************************/
  125. NINT UIO_Attention()
  126. {
  127.    FILE *inputFile;     /* extracts data from automate.dat */
  128.    FILE *tmpFile;       /* modified automate.dat including network run results */
  129.    TEXT input[DATLINELEN]; /* one text line from automate.dat */
  130.    TEXT *sp, *sp2, *spend; /* string pointers into various arrays */
  131.    NINT taskID;         /* Pro II/PLUS task to be performed */
  132.    NINT runResult;      /* return from processOneTask(); controls execution */
  133.    NINT i;
  134.  
  135.    /* perform all validations, file checks, and task syntax checks */
  136.    if ( (preScan ()) != UIO_OK) {
  137. #ifdef THINK_C
  138.       /* MAC version is multi-segment. Assume str.c is in second segment */
  139.       UnloadA4Seg(strcpy);
  140. #endif
  141.       return (UIO_ERROR);
  142.    }
  143.  
  144.    /* loop until all networks have been processed */
  145.    while (1) {
  146.       runResult = TASK_OK;
  147.  
  148.       /* open files */
  149.       inputFile = fopen ("automate.dat","r");
  150.       remove ("automate.tmp");
  151.       tmpFile = fopen ("automate.tmp", "w");
  152.       while ((sp=fgets (input, DATLINELEN, inputFile)) != 0) {
  153.          /* skip spaces, blank lines and comments.  Copy such lines into automate.tmp */
  154.          for (; *sp <= 0x20 && *sp != '\0'; sp++);
  155.          if (*sp != '!' && *sp != '\0')
  156.             break;
  157.          else
  158.             fprintf (tmpFile, "%s", input);
  159.       }
  160.  
  161.       /* exit program if all tasks in automate.dat have been processed */
  162.       if (sp == (char *)0)
  163.          break;
  164.  
  165.       /* we have read a command from automate.dat to be processed. */
  166.       /* parse the input line, reading the task */
  167.       for (sp = input; *sp <= 0x20 && *sp != '\0'; sp++); /* skip spaces, etc */
  168.       sp2 = sp; /* sp2 points to start of task string */
  169.       for (; *sp > 0x20 && *sp != ',' && *sp != '!'; sp++)
  170.          *sp = (TEXT) tolower (*sp);
  171.       i = (NINT) *sp; /* temporarily replace next chr with end of string */
  172.       *sp = '\0';
  173.  
  174.       if (      (strncmp (sp2, "open"      , 4 )) == 0) taskID = OPEN;
  175.       else if ( (strncmp (sp2, "learn"     , 4 )) == 0) taskID = LEARN;
  176.       else if ( (strncmp (sp2, "train"     , 4 )) == 0) taskID = LEARN;
  177.       else if ( (strncmp (sp2, "recall"    , 4 )) == 0) taskID = RECALL;
  178.       else if ( (strncmp (sp2, "test"      , 4 )) == 0) taskID = TEST;
  179.       else if ( (strncmp (sp2, "savebest"  , 5 )) == 0) taskID = SAVEBEST;
  180.       else if ( (strncmp (sp2, "initialize", 4 )) == 0) taskID = INITIALIZE;
  181.       else if ( (strncmp (sp2, "randomseed", 4 )) == 0) taskID = RANDOMSEED;
  182.       else if ( (strncmp (sp2, "seed"      , 4 )) == 0) taskID = RANDOMSEED;
  183.       else if ( (strncmp (sp2, "disable"   , 4 )) == 0) taskID = DISABLE;
  184.       else if ( (strncmp (sp2, "savenet"   , 5 )) == 0) taskID = SAVENET;
  185.       else if ( (strncmp (sp2, "set"       , 3 )) == 0) taskID = SETCMD;
  186.       else if ( (strncmp (sp2, "holdout"   , 4 )) == 0) taskID = HOLDOUT;
  187.  
  188.       *sp = (TEXT) i;  /* restore the chr */
  189.       if (*sp == ',')
  190.          sp++;         /* skip single comma */
  191.       for (; *sp <= 0x20 && *sp != '\0'; sp++); /* skip spaces after task id */
  192.  
  193.       /* parse remainder of line depending on the task.  'sp' points to first */
  194.       /* character in first parameter, or end of string. 'sp2' in not set */
  195.  
  196.       switch (taskID) {
  197.  
  198.        case OPEN:
  199.          parseString (&sp, NetworkFile, &NetworkFile[MAXFILESPEC]);
  200.          IsSetLearn = 0; /* open cmd kills previous 'set' commands */
  201.          IsSetTest  = 0;
  202.          IsSetDisable = 0;
  203.          FirstDisableTask = 1;
  204.          SavenetFile[0] = '\0'; /* kill any previous SAVENET filename */
  205.          break;
  206.  
  207.          /* savenet will overwrite the network currently in use if a new */
  208.          /* network filename is not specified */
  209.        case SAVENET:
  210.          parseString (&sp, SavenetFile, &SavenetFile[MAXFILESPEC]);
  211.          if (SavenetFile[0] == '\0')
  212.             strcpy (SavenetFile, NetworkFile);
  213.          break;
  214.  
  215.        case LEARN:
  216.          parseLong (&sp, &Long1);
  217.          break;
  218.  
  219.        case RECALL:      /* these tasks have no parameters */
  220.        case TEST:
  221.        case INITIALIZE:
  222.          break;
  223.  
  224.        case SAVEBEST:
  225.          parseLong (&sp, &Long1);
  226.          parseLong (&sp, &Long2);
  227.          parseLong (&sp, &Long3);
  228.          parseReal (&sp, &SbPruneTolerance);
  229.          parseInteger (&sp, &SbPruneMaxPEs);
  230.          break;
  231.  
  232.        case DISABLE:
  233.          /* differentiate between tasks DISABLE and DISABLE_ALL */
  234.          if ( (strncmp (sp, "all",  3 ) == 0) ||
  235.              (strncmp (sp, "each", 4 ) == 0) ||
  236.              (strncmp (sp, "every",5 ) == 0) ) {
  237.             taskID = DISABLE_ALL;
  238.             break;
  239.          }
  240.          /* read remaining numeric fields (pe numbers) */
  241.          for (i=0; i < DISABLEPES; i++)
  242.             if ( (parseInteger (&sp, &PeNumbers[i])) == 1 )
  243.                break;
  244.          break;
  245.  
  246.        case SETCMD:
  247.          sp2 = sp; /* sp2 points to start of task string */
  248.          for (; *sp > 0x20 && *sp != ',' && *sp != '!'; sp++)
  249.             *sp = (TEXT) tolower (*sp);
  250.          i = (NINT) *sp; /* temporarily replace next chr with end of string */
  251.          *sp = '\0';
  252.          IsSetLearn  = 0;
  253.          IsSetTest   = 0;
  254.          IsSetDisable= 0;
  255.          if      ( (strncmp (sp2, "learnfile" , 4 )) == 0) IsSetLearn = 1;
  256.          else if ( (strncmp (sp2, "recallfile", 4 )) == 0) IsSetTest  = 1;
  257.          else if ( (strncmp (sp2, "testfile"  , 4 )) == 0) IsSetTest  = 1;
  258.          else if ( (strncmp (sp2, "disable"   , 4 )) == 0) IsSetDisable=1;
  259.          *sp = (TEXT) i;  /* restore the chr */
  260.          if (*sp == ',')
  261.             sp++;         /* skip single comma */
  262.          for (; *sp <= 0x20 && *sp != '\0'; sp++); /* skip spaces after task id */
  263.          if (IsSetLearn) {
  264.             sp2 = LearnFile;
  265.             parseString (&sp, sp2, &sp2[MAXFILESPEC]);
  266.          }
  267.          else if (IsSetTest) {
  268.             sp2 = TestFile;
  269.             parseString (&sp, sp2, &sp2[MAXFILESPEC]);
  270.          }
  271.          /* else if (IsSetDisable) break  -- this set has no args */
  272.          break;
  273.  
  274.        case RANDOMSEED:
  275.          parseInteger (&sp, &RandomSeed);
  276.          break;
  277.  
  278.        case HOLDOUT:
  279.          parseReal (&sp, &SigmaStart);
  280.          parseReal (&sp, &SigmaStop);
  281.          parseReal (&sp, &SigmaStep);
  282.          break;
  283.  
  284.       } /* end switch */
  285.  
  286.       /* process the task */
  287.       fclose (tmpFile);
  288.       runResult = processOneTask (taskID);
  289.  
  290.       /* mark this line as being processed */
  291.       tmpFile = fopen ("automate.tmp", "a");
  292.       if (runResult == TASK_OK)
  293.          fprintf (tmpFile, "! Successful:  %s", input);
  294.       else if (runResult == TASK_INTRPT)
  295.          fprintf (tmpFile, "! Interrupted: %s", input);
  296.       else
  297.          fprintf (tmpFile, "! FAILURE:     %s", input);
  298.  
  299.       /* now copy the remaining text into the .tmp file and swap filenames */
  300.       while (fgets (input, DATLINELEN, inputFile) != 0)
  301.          fprintf (tmpFile, "%s", input);
  302.       fclose (tmpFile);
  303.       fclose (inputFile);
  304.       remove ("automate.dat");
  305.       rename ("automate.tmp", "automate.dat");
  306.  
  307.       if (runResult == TASK_INTRPT) {
  308.          PutStr("Do you wish to abort all tasks? (Y/n)");
  309.          sp = GetStr( );
  310.          if (*sp != 'n' && *sp != 'N')
  311.             break;
  312.       }
  313.    }  /* end while (1) */
  314.  
  315.    fclose (tmpFile);
  316.    remove ("automate.tmp");
  317.    fclose (inputFile);
  318. #ifdef MAC
  319.    SetTypeAndCreator ("automate.dat", "TEXT", "ttxt", -1);
  320. #ifdef THINK_C
  321.    /* MAC version is multi-segment. Assume str.c is in second segment */
  322.    UnloadA4Seg(strcpy);
  323. #endif
  324. #endif
  325.    return (UIO_OK);     /* normal end of program */
  326. }
  327.  
  328. /**************************************************************************/
  329. /*   preScan() reads and parses tasks in automate.dat to ensure there are */
  330. /*   no command errors or syntax errors present.                          */
  331. /**************************************************************************/
  332. NINT preScan()
  333. {
  334.    FILE *inputFile;     /* extracts data from automate.dat */
  335.    FILE *tmpFile;       /* modified automate.dat including network run results */
  336.    TEXT input[DATLINELEN]; /* one text line from automate.dat */
  337.    TEXT *sp, *sp2, *spend; /* string pointers into various arrays */
  338.    TEXT quoteChr;       /* filenames can be quoted (" or ') in automate.dat */
  339.    NINT parsingError;   /* flag == 1 if parsing error in task request */
  340.    NINT numErrors;      /* counter of parsingErrors */
  341.    NINT taskID;         /* Pro II/PLUS task to be performed */
  342.    NINT runResult;      /* return from processOneTask(); controls execution */
  343.    NINT i;
  344.  
  345.    numErrors = 0;
  346.    /* loop until all networks have been processed */
  347.    runResult = UIO_OK;
  348.    /* open automate.dat */
  349.    if ( (inputFile = fopen ("automate.dat","r")) == (FILE *)0 ) {
  350.       showMsg ("ERROR: Automate.dat must exist; press Enter to exit...", 0);
  351.       GetStr ();
  352.       return (UIO_EXIT);
  353.    }
  354.    else
  355.       PutStr ("Scanning automate.dat for syntax errors... ");
  356.    remove ("automate.tmp");
  357.    if ( (tmpFile = fopen ("automate.tmp", "w")) == (FILE *)0) {
  358.       showMsg ("ERROR: Unable to create automate.tmp; press Enter to exit...", 0);
  359.       GetStr ();
  360.       return (UIO_EXIT);
  361.    }
  362.    while (runResult != UIO_EXIT) {
  363.       while ((sp=fgets (input, DATLINELEN, inputFile)) != 0) {
  364.          /* skip spaces, blank lines and comments.  Copy such lines into automate.tmp */
  365.          for (sp = input; *sp <= 0x20 && *sp != '\0'; sp++);
  366.          if (*sp != '!' && *sp != '\0')
  367.             break;
  368.          else
  369.             fprintf (tmpFile, "%s", input);
  370.       }
  371.  
  372.       if (sp == (char *)0) {
  373.          /* automate.dat now has no commands remaining to be processed.  If we have */
  374.          /* processed any networks, then exit this routine. If the file existed but */
  375.          /* had nothing to be processed, display an error and exit.  */
  376.          if (NetworkFile[0] == '\0') {
  377.             showMsg ("ERROR: Automate.dat contains no new requests; press Enter to exit...", 0);
  378.             GetStr ();
  379.             runResult = UIO_EXIT;
  380.          }
  381.          else                   /* if here, we've finished the last network */
  382.             runResult = UIO_OK; /* in automate.dat; time to exit this routine */
  383.          break;      /* escape while loop, goto end of this routine */
  384.       }
  385.       /* we have read a command from automate.dat to be processed. */
  386.       /* parse the input line, reading the task */
  387.       for (sp = input; *sp <= 0x20 && *sp != '\0'; sp++); /* skip spaces, etc */
  388.       sp2 = sp; /* sp2 points to start of task string */
  389.       for (; *sp > 0x20 && *sp != ',' && *sp != '!'; sp++)
  390.          *sp = (TEXT) tolower (*sp);
  391.       i = (NINT) *sp; /* temporarily replace next chr with end of string */
  392.       *sp = '\0';
  393.  
  394.       taskID = -999; /* init to unknown taskID */
  395.       if (      (strncmp (sp2, "open"      , 4 )) == 0) taskID = OPEN;
  396.       else if ( (strncmp (sp2, "learn"     , 4 )) == 0) taskID = LEARN;
  397.       else if ( (strncmp (sp2, "train"     , 4 )) == 0) taskID = LEARN;
  398.       else if ( (strncmp (sp2, "recall"    , 4 )) == 0) taskID = RECALL;
  399.       else if ( (strncmp (sp2, "test"      , 4 )) == 0) taskID = TEST;
  400.       else if ( (strncmp (sp2, "savebest"  , 5 )) == 0) taskID = SAVEBEST;
  401.       else if ( (strncmp (sp2, "initialize", 4 )) == 0) taskID = INITIALIZE;
  402.       else if ( (strncmp (sp2, "randomseed", 4 )) == 0) taskID = RANDOMSEED;
  403.       else if ( (strncmp (sp2, "seed"      , 4 )) == 0) taskID = RANDOMSEED;
  404.       else if ( (strncmp (sp2, "disable"   , 4 )) == 0) taskID = DISABLE;
  405.       else if ( (strncmp (sp2, "savenet"   , 5 )) == 0) taskID = SAVENET;
  406.       else if ( (strncmp (sp2, "set"       , 3 )) == 0) taskID = SETCMD;
  407.       else if ( (strncmp (sp2, "holdout"   , 4 )) == 0) taskID = HOLDOUT;
  408.  
  409.       *sp = (TEXT) i;  /* restore the chr */
  410.       if (*sp == ',')
  411.          sp++;         /* skip single comma */
  412.       for (; *sp <= 0x20 && *sp != '\0'; sp++); /* skip spaces after task id */
  413.  
  414.       /* parse remainder of line depending on the task.  'sp' points to first */
  415.       /* character in first parameter, or end of string. 'sp2' in not set */
  416.       parsingError = 0;        /* assume success */
  417.       switch (taskID) {
  418.  
  419.          /* An OPEN task really requires a network name */
  420.        case OPEN:
  421.          if ( (parsingError = parseString (&sp, NetworkFile, &NetworkFile[MAXFILESPEC])) == 1) {
  422.             fprintf (tmpFile, "FAILURE: missing quote ->          %s", input);
  423.             break;
  424.          }
  425.          if (NetworkFile[0] == '\0') {
  426.             fprintf (tmpFile, "FAILURE: missing filename ->       %s", input);
  427.             parsingError = 1;
  428.             break;
  429.          }
  430.          /* the network is opened here as a final check, and also must be */
  431.          /* open for disable to check it's PE list */
  432.          if (ug_loadnet (NetworkFile) != UIO_OK) {
  433.             fprintf (tmpFile, "FAILURE: error opening network ->  %s", input);
  434.             parsingError = 1;
  435.             break;
  436.          }
  437.          IsSetDisable = 0;
  438.          IsSetLearn = 0;
  439.          IsSetTest = 0;
  440.          break;
  441.  
  442.          /* savenet will overwrite the network currently in use if a new */
  443.          /* network filename is not specified */
  444.        case SAVENET:
  445.          if ( (parsingError = parseString (&sp, SavenetFile, &SavenetFile[MAXFILESPEC])) == 1) {
  446.             fprintf (tmpFile, "FAILURE: missing quote ->          %s", input);
  447.             SavenetFile[0] = '\0';
  448.          }
  449.          break;
  450.  
  451.        case LEARN:
  452.          if ( (parsingError = parseLong (&sp, &Long1)) == 1)
  453.             fprintf (tmpFile, "FAILURE: learn count missing ->    %s", input);
  454.          break;
  455.  
  456.        case RECALL:      /* these tasks have no parameters */
  457.        case TEST:
  458.        case INITIALIZE:
  459.          break;
  460.  
  461.        case SAVEBEST:
  462.          if ( (parsingError = parseLong (&sp, &Long1)) == 1) {
  463.             fprintf (tmpFile, "FAILURE: learn count missing ->    %s", input);
  464.             break;
  465.          }
  466.          if ( (parsingError = parseLong (&sp, &Long2)) == 1) {
  467.             fprintf (tmpFile, "FAILURE: test frequency missing -> %s", input);
  468.             break;
  469.          }
  470.          if (Long2 > Long1) {
  471.             fprintf (tmpFile, "FAILURE: test freq > learn count-> %s", input);
  472.             parsingError = 1;
  473.             break;
  474.          }
  475.          Long3 = 0;                 /* three optional parameters */
  476.          SbPruneTolerance = 0.0;
  477.          SbPruneMaxPEs = 0;
  478.          parseLong (&sp, &Long3); /* this allows #retries to be zero, but */
  479.          /* will miss bad entries (i.e. alpha chrs) */
  480.          parsingError = parseReal (&sp, &SbPruneTolerance);
  481.          if (!parsingError)
  482.             parsingError = parseInteger (&sp, &SbPruneMaxPEs);
  483.          if (!parsingError)      /* okay if all 3 optional values are specified */
  484.             break;
  485.          if (SbPruneTolerance == 0.0 && SbPruneMaxPEs == 0) {
  486.             parsingError = 0;   /* okay if last 2 optional values are unspecified */
  487.             break;
  488.          }
  489.          fprintf (tmpFile, "FAILURE: # of retries missing? ->  %s", input);
  490.          parsingError = 1; /* error if 4 of 5 fields were entered */
  491.          break;
  492.  
  493.        case DISABLE:
  494.          /* differentiate between tasks DISABLE and DISABLE_ALL */
  495.          if ( (strncmp (sp, "all",  3 ) == 0) ||
  496.              (strncmp (sp, "each", 4 ) == 0) ||
  497.              (strncmp (sp, "every",5 ) == 0) ) {
  498.             taskID = DISABLE_ALL;
  499.             sp = &input[strlen (input)];
  500.             break;
  501.          }
  502.          /* read remaining numeric fields (pe numbers) */
  503.          for (i=0; i < DISABLEPES; i++)
  504.             if (parseInteger(&sp, &PeNumbers[i]))
  505.                break;
  506.          if (PeNumbers[0] == 0) {
  507.             fprintf (tmpFile, "FAILURE: no PEs listed ->          %s", input);
  508.             parsingError = 1;
  509.             break;
  510.          }
  511.          /* check the PE list for mistakes */
  512.          sp2 = SavenetFile;   /* using for junk storage */
  513.          NumInputPEs = 0;     /* only 1 arg below is wanted */
  514.          ug_rdnetinf (&i, &NumInputPEs, &i, &i, &sp2, &sp2); /* assumes net is opened */
  515.          for (i=0; i < DISABLEPES && PeNumbers[i] != 0; i++)
  516.             if (PeNumbers[i] < 2 || PeNumbers[i] > NumInputPEs+1) {
  517.                fprintf (tmpFile, "FAILURE: non-existent input PE ->  %s", input);
  518.                parsingError = 1;
  519.                break;
  520.             }
  521.          break;
  522.  
  523.        case SETCMD:
  524.          sp2 = sp; /* sp2 points to start of task string */
  525.          for (; *sp > 0x20 && *sp != ',' && *sp != '!'; sp++)
  526.             *sp = (TEXT) tolower (*sp);
  527.          i = (NINT) *sp; /* temporarily replace next chr with end of string */
  528.          *sp = '\0';
  529.          IsSetLearn  = 0;
  530.          IsSetTest   = 0;
  531.          IsSetDisable= 0;
  532.          if      ( (strncmp (sp2, "learnfile" , 4 )) == 0) IsSetLearn = 1;
  533.          else if ( (strncmp (sp2, "recallfile", 4 )) == 0) IsSetTest  = 1;
  534.          else if ( (strncmp (sp2, "testfile"  , 4 )) == 0) IsSetTest  = 1;
  535.          else if ( (strncmp (sp2, "disable"   , 4 )) == 0) IsSetDisable=1;
  536.          *sp = (TEXT) i;  /* restore the chr */
  537.          if (*sp == ',')
  538.             sp++;         /* skip single comma */
  539.          for (; *sp <= 0x20 && *sp != '\0'; sp++); /* skip spaces after task id */
  540.          if (IsSetLearn)
  541.             sp2 = LearnFile;
  542.          else if (IsSetTest)
  543.             sp2 = TestFile;
  544.          else if (IsSetDisable)
  545.             break;      /* no args, nothing to parse */
  546.          else {
  547.             fprintf (tmpFile, "FAILURE: unknown set command ->    %s", input);
  548.             parsingError = 1;
  549.             break;
  550.          }
  551.          if ( (parsingError = parseString (&sp, sp2, &sp2[MAXFILESPEC])) == 1) {
  552.             fprintf (tmpFile, "FAILURE: missing quote ->          %s", input);
  553.             break;
  554.          }
  555.          if (*sp2 == '\0') {
  556.             fprintf (tmpFile, "FAILURE: no filename specified ->  %s", input);
  557.             parsingError = 1;
  558.             break;
  559.          }
  560.          if ( (parsingError = fileNotFound (sp2, ".nna", 0)) == 1) {
  561.             fprintf (tmpFile, "FAILURE: file does not exist ->    %s", input);
  562.             break;
  563.          }
  564.          break;
  565.  
  566.        case RANDOMSEED:
  567.          if ( (parsingError = parseInteger (&sp, &RandomSeed)) == 1)
  568.             fprintf (tmpFile, "FAILURE: random seed missing ->    %s", input);
  569.          break;
  570.  
  571.        case HOLDOUT:
  572.          parseReal (&sp, &SigmaStart);                  /* allow any number */
  573.          parsingError = parseReal (&sp, &SigmaStop);    /* allow >= 0.0 */
  574.          if (parsingError && SigmaStop == 0.0)
  575.             parsingError = 0;
  576.          if (!parsingError)
  577.             parsingError = parseReal (&sp, &SigmaStep); /* disallow <= 0.0 */
  578.          if (!parsingError) {
  579.             if (SigmaStart > SigmaStop) {
  580.                fprintf (tmpFile, "FAILURE: sigmaStart > sigmaStop -> %s", input);
  581.                parsingError = 1;
  582.             }
  583.             else if (SigmaStep > SigmaStop) {
  584.                fprintf (tmpFile, "FAILURE: sigmaStop < sigmaStep ->  %s", input);
  585.                parsingError = 1;
  586.             }
  587.             break;
  588.          }
  589.          fprintf (tmpFile, "FAILURE: start,stop,step needed -> %s", input);
  590.          parsingError = 1;
  591.          break;
  592.  
  593.        default:
  594.          fprintf (tmpFile, "FAILURE: unrecognized task ->      %s", input);
  595.          parsingError = 1;
  596.          break;
  597.       } /* end switch */
  598.  
  599.       /* yield an error if too many fields were found */
  600.       if (!parsingError && *sp != '!' && *sp != '\0') {
  601.          fprintf (tmpFile, "FAILURE: too many fields ->        %s", input);
  602.          parsingError = 1;
  603.       }
  604.       if (parsingError)
  605.          numErrors++;
  606.       else
  607.          fprintf (tmpFile, "%s", input);
  608.    }  /* end while (runResult != UIO_EXIT) */
  609.  
  610.    fclose (tmpFile);
  611.    fclose (inputFile);
  612.    remove ("automate.dat");
  613.    rename ("automate.tmp", "automate.dat");
  614. #ifdef MAC
  615.    SetTypeAndCreator ("automate.dat", "TEXT", "ttxt", -1);
  616. #endif
  617.    if (runResult == UIO_EXIT)
  618.       return (UIO_EXIT);
  619.    else if (numErrors > 0) {
  620.       sprintf (input, "ERROR: Automate.dat contains %ld syntax errors; press Enter to exit...", (SL)numErrors);
  621.       showMsg (input, 0);
  622.       GetStr ();
  623.       return (UIO_EXIT);
  624.    }
  625.    else {
  626.       showMsg ("no errors found; continuing.", 1);
  627.       return (UIO_OK);
  628.    }
  629. }
  630.  
  631. #ifdef MAC
  632. #define WINDOW_COLOR  7
  633. #define TEXT_COLOR    4
  634. #else
  635. #define WINDOW_COLOR  4
  636. #define TEXT_COLOR    7
  637. #endif
  638.  
  639. /**************************************************************************/
  640. /* processOneTask - do the deed.  Global variables hold task parameters   */
  641. /**************************************************************************/
  642. NINT processOneTask (taskID)
  643. NINT taskID;                /* task being processed */
  644. {
  645.    APE  peData;             /* PE information for one PE, for disable */
  646.    TEXT title[150];         /* line containing task-in-progress info */
  647.    NINT windowColor;        /* window color */
  648.    NINT textColor;          /* text color */
  649.    TEXT buf[100];           /* work buffer for messages to user */
  650.    NINT runResult;          /* return value from this routine */
  651.    TEXT *sp, *spend;        /* string pointers */
  652.    NINT i, j;               /* work indices */
  653.    NINT rc;                 /* return code */
  654.  
  655.    runResult = TASK_OK;     /* assume a successful task */
  656.  
  657.    /* get graphics info & handle monochrome terminals */
  658.    ug_gparms (&xSize, &ySize, &i, &xChrSize, &yChrSize);
  659.    if (i < 8) {
  660.       windowColor = 1;
  661.       textColor   = 0;
  662.    } else {
  663.       windowColor = WINDOW_COLOR;
  664.       textColor   = TEXT_COLOR;
  665.    }
  666.  
  667.    switch (taskID) {
  668.  
  669.     case OPEN:     /* open the network */
  670.       if (ug_loadnet (NetworkFile) != 0) {
  671.          runResult = TASK_ERROR; /* NWorks displays an error message here. */
  672.          break;
  673.       }
  674.       /* network is now loaded; add '.nnd' if necessary */
  675.       for (sp = NetworkFile; *sp != '.' && *sp != '\0'; sp++);
  676.       spend = &NetworkFile[MAXFILESPEC-4];
  677.       if (*sp != '.' && sp < spend)
  678.          sprintf (sp, ".nnd");
  679.  
  680.       /* display the network and title line  */
  681.       ug_windel (0);                /* force network to display on screen */
  682.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  683.       sprintf (title, "Network %s opened.", NetworkFile);
  684.       i = strlen(title)*xChrSize;            /* center the title line */
  685.       i = (xSize - i) /2;
  686.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  687.       /* obtain information about this network */
  688.       sp = buf;  /* only 1 arg below is wanted */
  689.       ug_rdnetinf (&i, &NumInputPEs, &i, &i, &sp, &sp);
  690.       ug_randseed (0); /* reset so random file presentations stay same */
  691.       break;
  692.  
  693.     case SAVENET:
  694.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  695.       sprintf (title, "Saving network %s.", SavenetFile);
  696.       i = strlen(title)*xChrSize;            /* center the title line */
  697.       i = (xSize - i) /2;
  698.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  699.       SaveNet (SavenetFile, 0);              /* save in Binary mode */
  700.       break;
  701.  
  702.     case LEARN:
  703.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  704.       sprintf (title, "Training network %s for %ld Learns.", NetworkFile, Long1);
  705.       i = strlen(title)*xChrSize;            /* center the title line */
  706.       i = (xSize - i) /2;
  707.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  708.       if ( (rc=ug_learn (Long1)) < 0)
  709.          runResult = TASK_ERROR;
  710.       else if (rc&USER_INTRPT)
  711.          runResult = TASK_INTRPT;
  712.       else
  713.          SaveNet (NetworkFile, 0);              /* save in Binary mode */
  714.  
  715.       break;
  716.  
  717.     case TEST:
  718.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  719.       sprintf (title, "Testing network %s.", NetworkFile);
  720.       i = strlen(title)*xChrSize;            /* center the title line */
  721.       i = (xSize - i) /2;
  722.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  723.       if ( (rc=ug_test (0l)) < 0)
  724.          runResult = TASK_ERROR;
  725.       else if (rc&USER_INTRPT)
  726.          runResult = TASK_INTRPT;
  727.       break;
  728.  
  729.     case RECALL:
  730.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  731.       sprintf (title, "Recalling network %s.", NetworkFile);
  732.       i = strlen(title)*xChrSize;            /* center the title line */
  733.       i = (xSize - i) /2;
  734.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  735.       if ( (rc=ug_recall (0l)) < 0)
  736.          runResult = TASK_ERROR;
  737.       else if (rc&USER_INTRPT)
  738.          runResult = TASK_INTRPT;
  739.       break;
  740.  
  741.     case SAVEBEST:
  742.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  743.       sprintf (title, "Training %s", NetworkFile);
  744.       sp = &title[strlen(title)];
  745.       if (Long1 != 0)
  746.          sprintf (sp, " for %ld learns.", Long1);
  747.       sp = &title[strlen(title)-1];
  748.       sprintf (sp, ", testing every %ld learns.", Long2);
  749.       i = strlen(title)*xChrSize;         /* ensure title fits */
  750.       if ( i > xSize)
  751.          title[strlen(title)-8] = '\0';   /* remove ' learns.' if too long */
  752.       i = strlen(title)*xChrSize;         /* center the title line */
  753.       i = (xSize - i) /2;
  754.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  755.  
  756.       /* strip '.nnd' from string (if there) */
  757.       i = 0;  /* temp flag indicating whether '.nnd' was stripped */
  758.       if (NetworkFile[strlen (NetworkFile)-4] == '.') {
  759.          NetworkFile[strlen (NetworkFile)-4] = '\0';
  760.          i = 1;
  761.       }
  762.       j = 0;
  763.       if (SbPruneTolerance > 0.0 && SbPruneMaxPEs > 0)
  764.          j = 1;   /* temp flag == 1 if pruning parameters were entered */
  765.       /* note: assumes overwrite current net, logging */
  766.       if ((rc=ug_savebest (Long1, Long2, Long3, 1, NetworkFile,
  767.                            j, SbPruneMaxPEs, SbPruneTolerance)) < 0)
  768.          runResult = TASK_ERROR;
  769.       else if (rc&USER_INTRPT)
  770.          runResult = TASK_INTRPT;
  771.  
  772.       if (i == 1) /* restore the '.nnd' part of the filename */
  773.          NetworkFile[strlen (NetworkFile)] = '.';
  774.       break;
  775.  
  776.     case DISABLE_ALL:    /* disable each input PE one at a time in turn. */
  777.       /* if IsSetDisable is set, then ONLY the PEs will be disabled.  They are   */
  778.       /* not re-enabled, and no test is performed.  This is useful as a way to   */
  779.       /* disable particular PEs and save the net with them disabled.  It is      */
  780.       /* assumed that a savenet command will be encountered before opening       */
  781.       /* another network.                                                        */
  782.       if (!IsSetDisable && FirstDisableTask) {
  783.          /* upon first disable request, delete any previously existing graph output */
  784.          /* and perform the baseline test */
  785.          ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  786.          sprintf (title, "Baseline test of network %s.", NetworkFile);
  787.          j = strlen(title)*xChrSize;            /* center the title line */
  788.          j = (xSize - j) /2;
  789.          ug_puts (1, textColor, 0, j,yChrSize/4+1, title, 0);
  790.          remove ("disable.nnp");
  791.          if ((rc=ug_test (0l)) < 0)
  792.             runResult = TASK_ERROR;
  793.          else if (rc&USER_INTRPT)
  794.             runResult = TASK_INTRPT;
  795.          if ( (disableOutput ()) != 0)
  796.             runResult = TASK_ERROR;
  797.  
  798.          if (runResult != TASK_OK)
  799.             break;
  800.  
  801.          FirstDisableTask = 0;
  802.       } /* end !IsSetDisable */
  803.  
  804.       PeNumbers[1] = 0;
  805.       /* disable and test each PE in the input layer */
  806.       for (i=0; i < NumInputPEs; i++) {
  807.          ug_peio (&peData, 0, 0, i);          /* read pe info (layer 0) */
  808.          if (peData.ape_Flags &= 0x0002)      /* skip if already disabled */
  809.             continue;
  810.          peData.ape_Output = 0.0;             /* set it's output to 0.0 */
  811.          peData.ape_Flags |= 0x0002;          /* disable the PE */
  812.          ug_peio (&peData, 1, 0, i);          /* write the pe info */
  813.          if (IsSetDisable)  /* skip testing and re-enabling of PEs */
  814.             continue;
  815.          /* display the network showing the title line and disabled PE number */
  816.          PeNumbers[0] = i+2;
  817.          ug_windel (0);                         /* force network to display on screen */
  818.          ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  819.          sprintf (title, "Testing %s with PE %ld disabled.", NetworkFile, (SL)PeNumbers[0]);
  820.          j = strlen(title)*xChrSize;            /* center the title line */
  821.          j = (xSize - j) /2;
  822.          ug_puts (1, textColor, 0, j,yChrSize/4+1, title, 0);
  823.          /* perform a test command with this PE disabled */
  824.          if ((rc=ug_test (0l)) < 0)
  825.             runResult = TASK_ERROR;
  826.          else if (rc&USER_INTRPT)
  827.             runResult = TASK_INTRPT;
  828.  
  829.          /* enable the PE */
  830.          peData.ape_Flags &= ~0x0002;    /* enable the PE */
  831.          ug_peio (&peData, 1, 0, i);     /* write the pe info */
  832.          /* read disable.nnp and record results */
  833.          if ( (disableOutput ()) != 0)
  834.             runResult = TASK_ERROR;
  835.  
  836.          if (runResult != TASK_OK)
  837.             return(runResult);
  838.  
  839.       }
  840.       break;
  841.  
  842.     case DISABLE:    /* disable certain PEs entered on this task line */
  843.       /* if IsSetDisable is set, then ONLY the PEs will be disabled.  They are   */
  844.       /* not re-enabled, and no test is performed.  This is useful as a way to   */
  845.       /* disable particular PEs and save the net with them disabled.  It is      */
  846.       /* assumed that a savenet command will be encountered before opening       */
  847.       /* another network.                                                        */
  848.       if (!IsSetDisable && FirstDisableTask) {
  849.          /* upon first disable request, delete any previously existing graph output */
  850.          /* and perform the baseline test */
  851.          ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  852.          sprintf (title, "Baseline test of network %s.", NetworkFile);
  853.          i = strlen(title)*xChrSize;            /* center the title line */
  854.          i = (xSize - i) /2;
  855.          ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  856.          remove ("disable.nnp");
  857.          if ((rc=ug_test (0l)) < 0)
  858.             runResult = TASK_ERROR;
  859.          else if (rc&USER_INTRPT)
  860.             runResult = TASK_INTRPT;
  861.          if ( (disableOutput ()) != 0)
  862.             runResult = TASK_ERROR;
  863.          FirstDisableTask = 0;
  864.       } /* end !IsSetDisable */
  865.       /* now processing the disable PE request. Note that an input layer's first PE */
  866.       /* is PE number 2.  For example, IRIS networks have 4 inputs: PE2, PE3, PE4,  */
  867.       /* and PE5.  Internally this becomes 0 through 3 (the first PE of any layer   */
  868.       /* number 0).                                                                 */
  869.       /* disable the PEs */
  870.       for (i=0; i < DISABLEPES && PeNumbers[i] != 0; i++) {
  871.          ug_peio (&peData, 0, 0, PeNumbers[i]-2);    /* read pe info (layer 0) */
  872.          if (!(peData.ape_Flags &= 0x0002)) {        /* if not already disabled */
  873.             peData.ape_Output = 0.0;                 /* set it's output to 0.0 */
  874.             peData.ape_Flags |= 0x0002;              /* disable the PE */
  875.             ug_peio (&peData, 1, 0, PeNumbers[i]-2); /* write the pe info */
  876.          }
  877.          else
  878.             PeNumbers[i] *= -1;      /* mark this PE to prevent re-enabling */
  879.       }
  880.       if (IsSetDisable)  /* skip testing and re-enabling of PEs */
  881.          break;
  882.       /* display the network showing the title line and first disabled PE */
  883.       ug_windel (0);                         /* force network to display on screen */
  884.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  885.       if (PeNumbers[0] > 0)
  886.          sprintf (title, "Testing %s with disabled PEs. (%ld)", NetworkFile, (SL)PeNumbers[0]);
  887.       else
  888.          sprintf (title, "Testing %s with disabled PEs. (%ld)", NetworkFile, (SL)(-PeNumbers[0]));
  889.       i = strlen(title)*xChrSize;            /* center the title line */
  890.       i = (xSize - i) /2;
  891.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  892.       /* perform a test command with some PEs disabled */
  893.       if ((rc=ug_test (0l)) < 0)
  894.          runResult = TASK_ERROR;
  895.       else if (rc&USER_INTRPT)
  896.          runResult = TASK_INTRPT;
  897.       /* enable the PEs */
  898.       for (i=0; i < DISABLEPES && PeNumbers[i] != 0; i++)
  899.          if (PeNumbers[i] > 0) {                         /* skip PEs that were disabled to begin with */
  900.             ug_peio (&peData, 0, 0, PeNumbers[i]-2);     /* read pe info (layer 0) */
  901.             peData.ape_Flags &= ~0x0002;                 /* enable the PE */
  902.             ug_peio (&peData, 1, 0, PeNumbers[i]-2);     /* write the pe info */
  903.          }
  904.          else
  905.             PeNumbers[i] *= -1;     /* unmark a previously disabled PE */
  906.       /* read disable.nnp and record results */
  907.       if ( (disableOutput ()) != 0)
  908.          runResult = TASK_ERROR;
  909.  
  910.       if (runResult != TASK_OK)
  911.          return(runResult);
  912.  
  913.       break;
  914.  
  915.     case RANDOMSEED:
  916.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  917.       sprintf (title, "Resetting random seed for network %s.", NetworkFile);
  918.       i = strlen(title)*xChrSize;            /* center the title line */
  919.       i = (xSize - i) /2;
  920.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  921.       if ( (ug_randseed (RandomSeed)) != 0)
  922.          runResult = TASK_ERROR;
  923.       break;
  924.  
  925.     case INITIALIZE:
  926.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  927.       sprintf (title, "Initializing network %s.", NetworkFile);
  928.       i = strlen(title)*xChrSize;            /* center the title line */
  929.       i = (xSize - i) /2;
  930.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  931.       if ( (ug_netinit ()) != 0)
  932.          runResult = TASK_ERROR;
  933.       break;
  934.  
  935.     case SETCMD:
  936.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);    /* title window */
  937.       if (IsSetLearn)
  938.          sprintf (title, "Setting Learn filename to %s.", LearnFile);
  939.       else if (IsSetTest)
  940.          sprintf (title, "Setting Test filename to %s.", TestFile);
  941.       else if (IsSetDisable)
  942.          sprintf (title, "Disabling requested PE(s).");
  943.       i = strlen(title)*xChrSize;            /* center the title line */
  944.       i = (xSize - i) /2;
  945.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  946.       if (IsSetDisable)
  947.          break;
  948.       if (IsSetLearn) {
  949.          /* strip '.nna' if necessary.  Note that ug_fileio () requires this */
  950.          if (LearnFile[strlen (LearnFile)-4] == '.')
  951.             LearnFile[strlen (LearnFile)-4] = '\0';
  952.          /* values of -1 below default to current IO/Parameters settings */
  953.          if ( (ug_fileio (LearnFile, 0, -1, -1, -1)) != 0)
  954.             runResult = TASK_ERROR;
  955.       }
  956.       else if (IsSetTest) {
  957.          /* strip '.nna' if necessary */
  958.          if (TestFile[strlen (TestFile)-4] == '.')
  959.             TestFile[strlen (TestFile)-4] = '\0';
  960.          if ( (ug_fileio (TestFile, 1, -1, -1, -1)) != 0)
  961.             runResult = TASK_ERROR;
  962.       }
  963.       break;
  964.  
  965.     case HOLDOUT:
  966.       ug_window (1, windowColor, 0,ySize-((NINT)(yChrSize*1.6)), xSize,ySize);
  967.       sprintf (title, "Holdout Testing on %s.", NetworkFile);
  968.       i = strlen(title)*xChrSize;            /* center the title line */
  969.       i = (xSize - i) /2;
  970.       ug_puts (1, textColor, 0, i,yChrSize/4+1, title, 0);
  971.       runResult = runHoldOut ();
  972.       break;
  973.  
  974.     default:
  975.       runResult = TASK_ERROR;
  976.       break;
  977.    } /* end switch (taskID) */
  978.  
  979.    return (runResult);
  980. }
  981.  
  982. /**************************************************************************/
  983. /*  disableOutput - reads disable.nnp and appends to disable.log          */
  984. /**************************************************************************/
  985. NINT disableOutput ()
  986. {
  987.    TEXT  input[NNPLINELEN];  /* long enough for a 9x9 confusion matrix */
  988.    SREAL value[DISABLEPES];  /* R values from confusion matrixes */
  989.    SREAL testSum;            /* sum of R values */
  990.    NINT  valueIndex;         /* index into value array */
  991.    FILE  *f1, *f2;
  992.    NINT  i;
  993.  
  994.    /* open i/o files */
  995.    if ( (f1 = fopen ("disable.nnp", "r")) == (FILE *)0) {
  996.       showMsg ("Can't open instrument file 'disable.nnp'.", 0);
  997.       return (TASK_ERROR);
  998.    }
  999.    if ( (f2 = fopen ("disable.log", "a")) == (FILE *)0) {
  1000.       showMsg ("Can't open output file 'disable.log'.", 0);
  1001.       return (TASK_ERROR);
  1002.    }
  1003.    /* read R correlation values */
  1004.    valueIndex = -1;
  1005.    while ((fgets (input, NNPLINELEN, f1)) != 0)
  1006.       if (input[0] != '!' && input[0] != '\n') { /* skip comments and blanks */
  1007.          for (i=strlen(input)-2; input[i] > 0x20; i--); /* find last value */
  1008.          sscanf (&input[i], "%f", &value[++valueIndex]);
  1009.          if (valueIndex+1 == DISABLEPES)
  1010.             break;
  1011.       }
  1012.    valueIndex++;
  1013.    /* write headings if this is first output since the network was opened */
  1014.    if (FirstDisableTask) {
  1015.       fprintf (f2, "!%s! network:  %s%s", EolChr, NetworkFile, EolChr);
  1016.       if (valueIndex > 1) {
  1017.          fprintf (f2, "!  sum R  ");
  1018.          for (i=0; i < valueIndex; i++)
  1019.             fprintf (f2, " ConfM%ld ", (SL)(i+1));
  1020.       }
  1021.       else
  1022.          fprintf (f2, "!  R corr");
  1023.       fprintf (f2, " %%impact ---disabled PEs---%s", EolChr);
  1024.    }
  1025.    /* subtotal the test results; remember baseline sum for later comparison */
  1026.    testSum = 0.0;
  1027.    for (i=0; i < valueIndex; i++)
  1028.       testSum += value[i];
  1029.    if (FirstDisableTask)
  1030.       BaselineSum = testSum;
  1031.    /* write outputs.  NOTE:  order of last access of the confusion matrixes      */
  1032.    /* (ConfM), when dealing with more than 1, is important!  Before saving a     */
  1033.    /* network, users should edit and okay each in order: first the ConfM on      */
  1034.    /* the first (leftmost) output PE, then the second, etc.  This is needed      */
  1035.    /* because the order of execution of graphs (i.e. the order listed into       */
  1036.    /* the *.nnp file) is based upon the creation or access order of the graphs.  */
  1037.    /* If this is NOT performed, disable.log may unknowingly switch around the    */
  1038.    /* output node results.                                                       */
  1039.    if (valueIndex > 1)
  1040.       fprintf (f2, "% 8.4f ", testSum);   /* write sum of R */
  1041.    for (i = 0; i < valueIndex; i++)       /* write each output's R */
  1042.       fprintf (f2, "% 6.4f ", value[i]);
  1043.    /* write %impact (loss of accuracy caused by disabling these PEs) */
  1044.    testSum /= BaselineSum;
  1045.    testSum *= 100.0;
  1046.    testSum = 100.0 - testSum;
  1047.    fprintf (f2, "%7.3f ", testSum); /* will be negative if results improved */
  1048.    if (FirstDisableTask)
  1049.       fprintf (f2, " (baseline)");
  1050.    else
  1051.       for (i = 0; i < DISABLEPES && PeNumbers[i] != 0; i++)
  1052.          fprintf (f2, " %ld", (SL)PeNumbers[i]);
  1053.    fprintf (f2, "%s", EolChr);
  1054.    fclose (f1);
  1055.    fclose (f2);
  1056. #ifdef MAC
  1057.    SetTypeAndCreator ("disable.log", "TEXT", "ttxt", -1);
  1058. #endif
  1059.    remove ("disable.nnp");
  1060.    return (TASK_OK);
  1061. }
  1062.  
  1063. /****************************************************************************/
  1064. /* runHoldOut - Search for optimum Sigma Scale factor for PNN and GRNN nets */
  1065. /****************************************************************************/
  1066. NINT runHoldOut ()
  1067. {
  1068.    APE    peData;           /* PE structure; info for one PE */
  1069.    ALYR   layer;            /* Layer structure; info for one layer */
  1070.    ASCHED lrs;              /* Schedule structure; info for one L/R Schedule */
  1071.    NINT   *winMap;          /* dynamic memory pointer, 1 element per vector */
  1072.    NINT   *wwmp;            /* work winMap pointer */
  1073.    NINT   *classCount;      /* dynamic memory pointer, 1 element per output PE */
  1074.    NINT   *classCorrect;    /* dynamic memory pointer, 1 element per output PE */
  1075.    REAL   rmsAccumulate;    /* accumulator for GRNN rms measure */
  1076.    NINT   pnnLayer;         /* layer number of PNN or GRNN layer in net */
  1077.    NINT   pnnPEs;           /* number of PEs in PNN or GRNN layer */
  1078.    NINT   outputLayer;      /* layer number of output layer in net */
  1079.    NINT   outputPEs;        /* number of PEs in output layer */
  1080.    NINT   isPNN;            /* flag whether PNN net or GRNN net */
  1081.    SL     testVectors;      /* number of records in test data set */
  1082.    SREAL  highestOutput;    /* highest pattern layer output value */
  1083.    SREAL  classRate;        /* classification rate, if 1 of N outputs */
  1084.    SREAL  sigmaScale;       /* current sigma scale setting */
  1085.    FILE   *logFile;         /* output (appended) log file */
  1086.    SL     tmpLong;          /* temp long */
  1087.    TEXT   *sp;              /* temp string pointer */
  1088.    NINT   returnCode;       /* return value */
  1089.    TEXT   errorMsg[100];    /* i/o error messages */
  1090.    SREAL  bestSigma;        /* Best sigma from holdout */
  1091.    SREAL  bestMeasure;      /* saves best result from holdout runs */
  1092.    TEXT   testFN[20];       /* Recall/Test file name */
  1093.    NINT   i;
  1094.  
  1095.    winMap       = (NINT *)0;
  1096.    classCount   = (NINT *)0;
  1097.    classCorrect = (NINT *)0;
  1098.    logFile      = (FILE *)0;
  1099.    testFN[0]    = '\0';
  1100.    bestSigma    = 0.0;
  1101.  
  1102.    /* open output log file */
  1103.    if ((logFile = fopen ("holdout.log", "a")) == (FILE *)0) {
  1104.       strcpy (errorMsg, "Can't open output file 'holdout.log'.");
  1105.       goto taskError;
  1106.    }
  1107.    ug_rdfileinf (&sp, 1, &testVectors);    /* fetch filename of test data */
  1108.    strncpy(testFN, sp, 20);                /* Save the file name */
  1109.    testFN[19] = '\0';                      /* so we retore it later */
  1110.  
  1111.    /* fetch # vectors, and set Test command to run from the training file */
  1112.    ug_rdfileinf (&sp, 0, &testVectors);    /* fetch filename of learn data */
  1113.    if (testVectors <= 0l) {
  1114.       strcpy (errorMsg, "Error reading training data set (missing file?)");
  1115.       goto taskError;
  1116.    }
  1117.  
  1118.    if ( (ug_fileio (sp, 1, -1, -1, -1)) != 0) { /* test from learn data set */
  1119.       strcpy (errorMsg, "Unexpected error calling ug_fileio().");
  1120.       goto taskError;
  1121.    }
  1122.  
  1123.    /* fetch output layer number & #PEs */
  1124.    ug_rdnetinf (&outputLayer, &i, &outputPEs, &i, &sp, &sp);
  1125.    outputLayer--;
  1126.  
  1127.    /* allocate dynamic memory */
  1128.    if ((winMap = (NINT *) malloc (sizeof(NINT)*testVectors)) == (NINT *)0) {
  1129.       strcpy (errorMsg, "Insufficient memory for winMap array.");
  1130.       goto taskError;
  1131.    }
  1132.    if ((classCount = (NINT *) malloc (sizeof(NINT)*outputPEs)) == (NINT *)0) {
  1133.       strcpy (errorMsg, "Insufficient memory for classCount array.");
  1134.       goto taskError;
  1135.    }
  1136.    if ((classCorrect = (NINT *) malloc (sizeof(NINT)*outputPEs)) == (NINT *)0) {
  1137.       strcpy (errorMsg, "Insufficient memory for classCorrect array.");
  1138.       goto taskError;
  1139.    }
  1140.  
  1141.    /* init arrays */
  1142.    for (i=0; i < outputPEs; i++) {
  1143.       classCount[i] = 0;
  1144.       classCorrect[i] = 0;
  1145.    }
  1146.  
  1147.    /* locate the PNN or GRNN pattern layer and fetch #PEs */
  1148.    pnnPEs = 0;
  1149.    isPNN  = 0;
  1150.    for (i=1; i < outputLayer; i++) {
  1151.       ug_lyrio (&layer, 0, i);       /* read layer info for this layer */
  1152.       /* 17 is PNN directory list item; 19 is GRNN directory list item */
  1153.       if (layer.tran_f == 17 || layer.tran_f == 19) {
  1154.          pnnLayer = i;
  1155.          pnnPEs = layer.num_pes;
  1156.          if (layer.tran_f == 17)
  1157.             isPNN = 1;
  1158.          break;
  1159.       }
  1160.    }
  1161.    if (pnnPEs == 0) {
  1162.       strcpy (errorMsg, "Can't find PNN/GRNN pattern layer (wrong net type?)");
  1163.       goto taskError;
  1164.    }
  1165.  
  1166.    if (isPNN)
  1167.       bestMeasure  = -10000.0;
  1168.    else
  1169.       bestMeasure  = 10000.0;
  1170.  
  1171.    /* fetch current Sigma Scale coefficient from L/R schedule */
  1172.    ug_schdio (&lrs, 0, pnnLayer);
  1173.    sigmaScale = lrs.asc_col[0].asc_rcl[5];
  1174.  
  1175.    /* setup sigma start,stop,step.  A negative sigma start means that we    */
  1176.    /* will interpret the start/stop settings to be offsets from the current */
  1177.    /* sigma scale  (positive sigma start means absolute addressing,         */
  1178.    /* negative sigma start means relative addressing).  Also, Sigma Scale   */
  1179.    /* should never become zero or less than zero. */
  1180.  
  1181.    if (SigmaStart < 0.0) {
  1182.       SigmaStart += sigmaScale;
  1183.       if (SigmaStart < 0.00001)
  1184.          SigmaStart = 0.00001;
  1185.       SigmaStop += sigmaScale;
  1186.    }
  1187.    sigmaScale = SigmaStart;
  1188.  
  1189.    /* write logfile headers */
  1190.    fprintf (logFile, "Holdout testing of network %s%s", NetworkFile, EolChr);
  1191.    fprintf (logFile,
  1192.             "Sigma Scale varies from %6.4f to %6.4f, stepped by %6.4f%s",
  1193.             SigmaStart, SigmaStop, SigmaStep, EolChr);
  1194.    fflush(logFile);
  1195.  
  1196.    /* run through training data; setup win map and count vectors per class */
  1197.    for (tmpLong=0l, wwmp=winMap; tmpLong < testVectors; tmpLong++,wwmp++) {
  1198.       if ((returnCode = ug_test (1l)) < 0) {
  1199.          strcpy (errorMsg, "An error occurred running the Test command.");
  1200.          goto taskError;
  1201.       }
  1202.       else if (returnCode & USER_INTRPT)
  1203.          goto taskInterrupt;
  1204.       highestOutput = -10000.0;
  1205.       for (i=0; i < pnnPEs; i++) {
  1206.          ug_peio (&peData, 0, pnnLayer, i);  /* read PNN/GRNN layer PE */
  1207.          if (peData.ape_Output > highestOutput) {
  1208.             *wwmp = i;         /* set winning PE # for this vector */
  1209.             highestOutput = peData.ape_Output;
  1210.          }
  1211.       }
  1212.       if (isPNN) {
  1213.          for (i=0; i < outputPEs; i++) {
  1214.             ug_peio (&peData, 0, outputLayer, i);   /* read Output layer PE */
  1215.             if (peData.ape_Err > .5)               /* desired output */
  1216.                classCount[i]++;
  1217.          }
  1218.       }
  1219.    }
  1220.  
  1221.    /* run holdout tests.  Loop through data once per sigma scale setting */
  1222.    while (1) {
  1223.       rmsAccumulate = 0.0;
  1224.       for (i=0; i < outputPEs; i++)
  1225.          classCorrect[i] = 0;
  1226.       /* write current Sigma Scale coefficient into L/R schedule */
  1227.       if (sigmaScale < 0.00001)
  1228.          sigmaScale = 0.00001; /* If < 0.00001 will use old Neuro-dynamics */
  1229.       lrs.asc_col[0].asc_rcl[5] = sigmaScale;
  1230.       ug_schdio (&lrs, 1, pnnLayer);
  1231.  
  1232.       for (tmpLong=0l,wwmp=winMap; tmpLong < testVectors; tmpLong++,wwmp++) {
  1233.          NINT highestIndex1, highestIndex2;
  1234.  
  1235.          /* disable this vector's pattern layer PE */
  1236.          ug_peio (&peData, 0, pnnLayer, *wwmp); /* read pe info */
  1237.          peData.ape_Output = 0.0;                      /* zero it's output */
  1238.          peData.ape_Flags |= 0x0002;                      /* disable the PE */
  1239.          ug_peio (&peData, 1, pnnLayer, *wwmp); /* write PE info */
  1240.          /* test this vector only, and accumulate RMS Error */
  1241.          if ((returnCode = ug_test (1l)) < 0) {
  1242.             strcpy (errorMsg, "An error occurred running the Test command.");
  1243.             goto taskError;
  1244.          } else if (returnCode & USER_INTRPT)
  1245.             goto taskInterrupt;
  1246.  
  1247.          highestOutput = -10000.0;
  1248.          highestIndex1 = -1;
  1249.          highestIndex2 = -1;
  1250.  
  1251.          for (i=0; i < outputPEs; i++) {
  1252.             APE wpe;   /* work pe */
  1253.  
  1254.             ug_peio (&wpe, 0, outputLayer, i);  /* read Output layer PE */
  1255.             if (isPNN) {
  1256.                if (wpe.ape_Output > highestOutput) {
  1257.                   highestIndex1 = i;
  1258.                   highestOutput = wpe.ape_Output;
  1259.                }
  1260.                if (wpe.ape_Err > 0.5)
  1261.                   highestIndex2 = i;
  1262.             } else {  /* calculate rms for this vector */
  1263.                rmsAccumulate +=
  1264.                   ((wpe.ape_Err - wpe.ape_Output) *
  1265.                    (wpe.ape_Err - wpe.ape_Output)) / ((REAL)outputPEs);
  1266.             }
  1267.          }
  1268.          if (isPNN                       &&
  1269.              highestIndex1 >= 0          &&
  1270.              highestIndex1==highestIndex2)
  1271.             classCorrect[highestIndex1]++;
  1272.  
  1273.          /* enable the PE */
  1274.          peData.ape_Flags &= ~0x0002;                      /* enable the PE */
  1275.          ug_peio (&peData, 1, pnnLayer, *wwmp);  /* write PE info */
  1276.       }
  1277.  
  1278.       /* write log file results */
  1279.       if (isPNN) {   /* is PNN use classRate; if GRNN use rmsError */
  1280.          classRate = 0.0;
  1281.          for (i=0; i < outputPEs; i++) {
  1282.             if (classCount[i] > 0)
  1283.                classRate += classCorrect[i] / (SREAL)classCount[i];
  1284.          }
  1285.          classRate /= (SREAL)outputPEs;
  1286.  
  1287.          if (classRate > bestMeasure) {
  1288.             bestMeasure = classRate;
  1289.             bestSigma = sigmaScale;
  1290.          }
  1291.          fprintf (logFile,
  1292.                   "   avg classification rate = %6.4f, sigma scale = %6.4f%s",
  1293.                   classRate, sigmaScale, EolChr);
  1294.       } else {
  1295.          rmsAccumulate /= (double)(testVectors);
  1296.          rmsAccumulate = sqrt(rmsAccumulate);
  1297.          if (rmsAccumulate < bestMeasure) {
  1298.             bestMeasure = rmsAccumulate;
  1299.             bestSigma = sigmaScale;
  1300.          }
  1301.          fprintf (logFile,
  1302.                   "   root-mean-square error = %6.4f, sigma scale = %6.4f%s",
  1303.                   rmsAccumulate, sigmaScale, EolChr);
  1304.       }
  1305.       fflush(logFile);
  1306.  
  1307.       /* setup for next loop or exit from loop */
  1308.       if (sigmaScale + SigmaStep <= SigmaStop)
  1309.          sigmaScale += SigmaStep;
  1310.       else if (sigmaScale < SigmaStop)
  1311.          sigmaScale = SigmaStop;
  1312.       else
  1313.          break;
  1314.  
  1315.    } /* end while (1) */
  1316.  
  1317.    /* write best Sigma Scale coefficient into L/R schedule */
  1318.    lrs.asc_col[0].asc_rcl[5] = bestSigma;
  1319.    ug_schdio (&lrs, 1, pnnLayer);
  1320.  
  1321.    returnCode = TASK_OK;
  1322.  
  1323.  
  1324. endRoutine:
  1325.    if (logFile != (FILE *)0) {
  1326.       fprintf (logFile, "%s", EolChr);
  1327.       fclose (logFile);
  1328. #ifdef MAC
  1329.       SetTypeAndCreator ("holdout.log", "TEXT", "ttxt", -1);
  1330. #endif
  1331.    }
  1332.    if (winMap != (NINT *)0)
  1333.       free (winMap);
  1334.    if (classCount != (NINT *)0)
  1335.       free (classCount);
  1336.    if (classCorrect != (NINT *)0)
  1337.       free (classCorrect);
  1338.    if (testFN[0] != '\0')
  1339.       ug_fileio (testFN, 1, -1, -1, -1); /* Restore test file name */
  1340.    return (returnCode);
  1341.  
  1342. taskError:
  1343.    showMsg (" ", 1);
  1344.    showMsg (errorMsg, 0);
  1345.    if (logFile != (FILE *)0)
  1346.       fprintf (logFile, "%s%s", errorMsg, EolChr);
  1347.    returnCode = TASK_ERROR;
  1348.    goto endRoutine;
  1349.  
  1350. taskInterrupt:
  1351.    returnCode = TASK_INTRPT;
  1352.    goto endRoutine;
  1353. }
  1354.  
  1355. /**************************************************************************/
  1356. /*  parseString - extract a string (with or without quotes) from input    */
  1357. /**************************************************************************/
  1358. NINT parseString (sp, sp2, spend)
  1359. TEXT **sp, *sp2, *spend;        /* string pointers */
  1360. {
  1361.    TEXT quoteChr;
  1362.    NINT tooMuchData;    /* flag == 1 if more data than array elements */
  1363.  
  1364.    tooMuchData = 0;
  1365.    *sp2 = '\0';
  1366.    if (**sp == '"' || **sp == '\'') {
  1367.       quoteChr = **sp;
  1368.       for ((*sp)++; **sp != '\0' && **sp != quoteChr && sp2 < spend;
  1369.            *sp2 = **sp, (*sp)++, sp2++);  /* fill array */
  1370.       if (**sp == quoteChr) {
  1371.          *sp2 = '\0';
  1372.          (*sp)++;            /* skip quote */
  1373.          if (**sp == ',')  /* skip single comma */
  1374.             (*sp)++;
  1375.          for (; **sp <= 0x20 && **sp != '\0'; (*sp)++);   /* skip spaces, etc */
  1376.          return (0);
  1377.       }
  1378.       if (sp2 == spend)    /* tooMuchData found */
  1379.          for (; **sp > 0x20 && **sp != ',' && **sp != '!'; (*sp)++);  /* skip digits */
  1380.       if (**sp == ',')  /* skip single comma */
  1381.          (*sp)++;
  1382.       for (; **sp <= 0x20 && **sp != '\0'; (*sp)++);      /* skip spaces, etc */
  1383.       return (1);
  1384.    }
  1385.  
  1386.    /* not quoted */
  1387.    for (; **sp > 0x20 && **sp != ',' && **sp != '!' && sp2 < spend;
  1388.         *sp2 = **sp, (*sp)++, sp2++);  /* fill array */
  1389.    *sp2 = '\0';
  1390.    if (sp2 == spend && **sp > 0x20 && **sp != ',' && **sp != '!')
  1391.       tooMuchData = 1;
  1392.    if (sp2 == spend)
  1393.       for (; **sp > 0x20 && **sp != ',' && **sp != '!'; (*sp)++);  /* skip digits */
  1394.    if (**sp == ',')  /* skip single comma */
  1395.       (*sp)++;
  1396.    for (; **sp <= 0x20 && **sp != '\0'; (*sp)++);         /* skip spaces, etc */
  1397.  
  1398.    sp2--;
  1399.    if (tooMuchData || *sp2 == '"' || *sp2 == '\'') {
  1400.       return (1);
  1401.    }
  1402.    return (0);
  1403. }
  1404.  
  1405. /**************************************************************************/
  1406. /*  parseLong - extract a Long numeric value from input                   */
  1407. /**************************************************************************/
  1408. NINT parseLong (sp, value)
  1409. TEXT **sp;
  1410. SL   *value;   /* returned number */
  1411. {
  1412.    NINT rc;
  1413.  
  1414.    if (sscanf(*sp, "%ld", value) <= 0) {
  1415.       rc = 1;
  1416.       *value = 0l;
  1417.    } else
  1418.       rc = 0;
  1419.  
  1420.    for (; **sp > 0x20 && **sp != ',' && **sp != '!'; (*sp)++);  /* skip digits */
  1421.    if (**sp == ',')
  1422.       (*sp)++;   /* skip single comma */
  1423.    for (; **sp <= 0x20 && **sp != '\0'; (*sp)++);         /* skip spaces, etc */
  1424.  
  1425.    /* Only return 0 if positive */
  1426.    if (rc || (*value) <= 0l)
  1427.       return(1);
  1428.    else
  1429.       return(0);
  1430. }
  1431.  
  1432. /**************************************************************************/
  1433. /*  parseInteger - extract a Integer numeric value from input             */
  1434. /**************************************************************************/
  1435. NINT parseInteger (sp, value)
  1436. TEXT **sp;
  1437. NINT *value;   /* returned number */
  1438. {
  1439.    SL   wl;     /* work long */
  1440.    NINT rc;
  1441.  
  1442.    if (sscanf(*sp, "%ld", &wl) <= 0) {
  1443.       rc = 1;
  1444.       *value = 0;
  1445.    } else {
  1446.       rc = 0;
  1447.       *value = (NINT)wl;
  1448.    }
  1449.  
  1450.    for (; **sp > 0x20 && **sp != ',' && **sp != '!'; (*sp)++);  /* skip digits */
  1451.    if (**sp == ',')
  1452.       (*sp)++;   /* skip single comma */
  1453.    for (; **sp <= 0x20 && **sp != '\0'; (*sp)++);     /* skip spaces, etc */
  1454.  
  1455.    /* Only return 0 if positive */
  1456.    if (rc || (*value) <= 0)
  1457.       return(1);
  1458.    else
  1459.       return(0);
  1460. }
  1461.  
  1462. /**************************************************************************/
  1463. /*  parseReal - extract a Real (float) value from input                   */
  1464. /**************************************************************************/
  1465. NINT parseReal (sp, value)
  1466. TEXT **sp;
  1467. SREAL *value;  /* returned number */
  1468. {
  1469.    NINT rc;
  1470.  
  1471.    if (sscanf(*sp, "%f", value) <= 0) {
  1472.       *value = 0.0;
  1473.       rc = 1;
  1474.    } else
  1475.       rc = 0;
  1476.  
  1477.    for (; **sp > 0x20 && **sp != ',' && **sp != '!'; (*sp)++);  /* skip digits */
  1478.    if (**sp == ',')
  1479.       (*sp)++;   /* skip single comma */
  1480.    for (; **sp <= 0x20 && **sp != '\0'; (*sp)++);     /* skip spaces, etc */
  1481.  
  1482.    /* Only return 0 if positive */
  1483.    if (rc || (*value) <= 0.0)
  1484.       return(1);
  1485.    else
  1486.       return(0);
  1487. }
  1488.  
  1489. /**************************************************************************/
  1490. /*  fileNotFound - check to see file exists and can be opened             */
  1491. /**************************************************************************/
  1492. NINT fileNotFound (fileName, defaultExt, extOptional)
  1493. TEXT *fileName, *defaultExt;
  1494. NINT extOptional;          /* flag == 1 if filename extention is optional */
  1495. {
  1496.    TEXT testName[MAXFILESPEC];
  1497.    TEXT *sp;
  1498.    FILE *testOpen;
  1499.  
  1500.    /* note: this routine does NOT fixup bad file extentions! */
  1501.    strcpy (testName, fileName);
  1502.  
  1503.    if (extOptional) {
  1504.       if ( (testOpen = fopen (testName, "r")) != (FILE *)0) {
  1505.          fclose (testOpen);
  1506.          return (0);        /* good return; file does exist */
  1507.       }
  1508.    }
  1509.  
  1510.    /* note: routine requires defaultExt passed with '.' and in lowercase! */
  1511.    if (*defaultExt != '.')
  1512.       return (1);
  1513.  
  1514.    /* add default extention if name currently has no extention */
  1515.    for (sp = testName; *sp != '.' && *sp != '\0'; sp++);
  1516.    if (*sp != '.' && sp < &testName[MAXFILESPEC-4])
  1517.       sprintf (sp, defaultExt); /* 'sp' now (probably) points at '.' */
  1518.  
  1519.    sp++;       /* ensure extentions are the same */
  1520.    defaultExt++;
  1521.    if ((TEXT)tolower(*sp) != *defaultExt)
  1522.       return (1);
  1523.    sp++;
  1524.    defaultExt++;
  1525.    if ((TEXT)tolower(*sp) != *defaultExt)
  1526.       return (1);
  1527.    sp++;
  1528.    defaultExt++;
  1529.    if ((TEXT)tolower(*sp) != *defaultExt)
  1530.       return (1);
  1531.  
  1532.    if ( (testOpen = fopen (testName, "r")) != (FILE *)0) {
  1533.       fclose (testOpen);
  1534.       return (0);        /* good return; file does exist */
  1535.    }
  1536.  
  1537.    return (1);          /* couldn't find it 'nohow' */
  1538. }
  1539.  
  1540. /**************************************************************************/
  1541. /*  showMsg - displays message on screen                                  */
  1542. /**************************************************************************/
  1543. VOID showMsg (text, eolFlag)
  1544. TEXT *text;
  1545. NINT eolFlag;     /* 0=no eol; 1=eol */
  1546. {
  1547.    PutStr (text);                         /* display to screen */
  1548.    if (eolFlag == 1)
  1549.       PutStr (EolChr);  /* newline */
  1550. }
  1551.  
  1552. /**************************************************************************/
  1553. /*   A User Control program needs the following functions only to avoid   */
  1554. /*   link errors. You do not need to provide code for any of them.        */
  1555. /**************************************************************************/
  1556.  
  1557. NINT UIO_Learn_Start()
  1558. {
  1559.    return(UIO_OK);
  1560. }
  1561. NINT UIO_Learn_Input(LayN, nPEs, Datap)
  1562. NINT  LayN;
  1563. NINT  nPEs;
  1564. SREAL *Datap;
  1565. {
  1566.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1567.    return(UIO_OK);
  1568. }
  1569. NINT UIO_Learn_Output(LayN, nPEs, Datap)
  1570. NINT  LayN;
  1571. NINT  nPEs;
  1572. SREAL *Datap;
  1573. {
  1574.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1575.    return(UIO_OK);
  1576. }
  1577. NINT UIO_Learn_Result(LayN, nPEs, Datap)
  1578. NINT  LayN;
  1579. NINT  nPEs;
  1580. SREAL *Datap;
  1581. {
  1582.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1583.    return(UIO_OK);
  1584. }
  1585. NINT UIO_Learn_End()
  1586. {
  1587.    return(UIO_OK);
  1588. }
  1589. NINT UIO_Recall_Start()
  1590. {
  1591.    return(UIO_OK);
  1592. }
  1593. NINT UIO_Read(LayN, nPEs, Datap)
  1594. NINT  LayN;
  1595. NINT  nPEs;
  1596. SREAL *Datap;
  1597. {
  1598.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1599.    return(UIO_OK);
  1600. }
  1601. NINT UIO_Write(LayN, nPEs, Datap)
  1602. NINT  LayN;
  1603. NINT  nPEs;
  1604. SREAL *Datap;
  1605. {
  1606.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1607.    return(UIO_OK);
  1608. }
  1609. NINT UIO_Write_Step(LayN, nPEs, Datap)
  1610. NINT  LayN;
  1611. NINT  nPEs;
  1612. SREAL *Datap;
  1613. {
  1614.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1615.    return(UIO_OK);
  1616. }
  1617. NINT UIO_Recall_Test(LayN, nPEs, Datap)
  1618. NINT  LayN;
  1619. NINT  nPEs;
  1620. SREAL *Datap;
  1621. {
  1622.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1623.    return(UIO_OK);
  1624. }
  1625. NINT UIO_Recall_End()
  1626. {
  1627.    return(UIO_OK);
  1628. }
  1629. NINT UIO_Instrument(Instrument_id, nDataElems, DataElemp)
  1630. NINT  Instrument_id;
  1631. NINT  nDataElems;
  1632. SREAL *DataElemp;
  1633. {
  1634.    Instrument_id=Instrument_id;        /* compiler be quiet! */
  1635.    nDataElems=nDataElems; DataElemp=DataElemp;  /* be quiet! */
  1636.    return(UIO_OK);
  1637. }
  1638. NINT UIO_Rewind()
  1639. {
  1640.    return(UIO_OK);
  1641. }
  1642. NINT UIO_Explain(LayN, nPEs, Datap)
  1643. NINT  LayN;
  1644. NINT  nPEs;
  1645. SREAL *Datap;
  1646. {
  1647.    LayN=LayN; nPEs=nPEs; Datap=Datap;  /* compiler be quiet! */
  1648.    return(UIO_OK);
  1649. }
  1650. NINT UIO_ObjFunc(eoeflag, Datap)
  1651. NINT eoeflag;
  1652. SREAL *Datap;
  1653. {
  1654.    eoeflag=eoeflag; Datap=Datap;       /* compiler be quiet! */
  1655.    return(UIO_OK);
  1656. }
  1657.  
  1658.  
  1659. #ifdef MAC
  1660. OSType string2OSType (char *s)
  1661. {
  1662.    OSType *ret;
  1663.  
  1664.    ret = (OSType *)s;
  1665.    return (*ret);
  1666. }
  1667.  
  1668. OSErr SetTypeAndCreator (char *fnp, char *typ, char *crea, short vref)
  1669. {
  1670.    OSErr err;
  1671.    FInfo finfo;
  1672.    OSType type, creator;
  1673.    Str255  name;
  1674.  
  1675.    if (vref == -1) { /* get current vref and use it */
  1676.       if ((err = GetVol(&name[0],&vref)) != noErr)
  1677.          return err;
  1678.    }
  1679.  
  1680.    err = GetFInfo( (StringPtr) c2pstr(fnp), vref, &finfo );
  1681.  
  1682.    if (err  == noErr) {
  1683.       type = string2OSType (typ);
  1684.       creator = string2OSType (crea);
  1685.       if (finfo.fdType != type  ||  finfo.fdCreator != creator) {
  1686.          finfo.fdType = type;
  1687.          finfo.fdCreator = creator;
  1688.          err = SetFInfo((StringPtr) fnp, vref, &finfo);
  1689.       }
  1690.    }
  1691.    p2cstr(fnp);
  1692.    return err;
  1693. }
  1694. #endif /* MAC */
  1695.